<?php
// 作者: yujianyue <15058593138@qq.com>
// 演示地址: http://sudu.chalide.cn

session_start();

// 数独类
class Sudoku {
    private $board = [];
    private $solution = [];
    private $size = 9;
    private $difficulty = 'medium';
    
    public function __construct($size = 9, $difficulty = 'medium') {
        $this->size = $size;
        $this->difficulty = $difficulty;
        $this->board = array_fill(0, $size, array_fill(0, $size, 0));
        $this->solution = array_fill(0, $size, array_fill(0, $size, 0));
    }
    
    // 检查数字是否可以放置在指定位置
    public function isValidMove($board, $row, $col, $num) {
        // 检查行
        for ($i = 0; $i < $this->size; $i++) {
            if ($board[$row][$i] == $num) return false;
        }
        
        // 检查列
        for ($i = 0; $i < $this->size; $i++) {
            if ($board[$i][$col] == $num) return false;
        }
        
        // 检查3x3方格
        if ($this->size == 9) {
            $boxRow = floor($row / 3) * 3;
            $boxCol = floor($col / 3) * 3;
            for ($i = $boxRow; $i < $boxRow + 3; $i++) {
                for ($j = $boxCol; $j < $boxCol + 3; $j++) {
                    if ($board[$i][$j] == $num) return false;
                }
            }
        } else if ($this->size == 4) {
            $boxRow = floor($row / 2) * 2;
            $boxCol = floor($col / 2) * 2;
            for ($i = $boxRow; $i < $boxRow + 2; $i++) {
                for ($j = $boxCol; $j < $boxCol + 2; $j++) {
                    if ($board[$i][$j] == $num) return false;
                }
            }
        }
        
        return true;
    }
    
    // 使用回溯算法求解数独
    public function solveSudoku(&$board) {
        for ($row = 0; $row < $this->size; $row++) {
            for ($col = 0; $col < $this->size; $col++) {
                if ($board[$row][$col] == 0) {
                    for ($num = 1; $num <= $this->size; $num++) {
                        if ($this->isValidMove($board, $row, $col, $num)) {
                            $board[$row][$col] = $num;
                            if ($this->solveSudoku($board)) {
                                return true;
                            }
                            $board[$row][$col] = 0;
                        }
                    }
                    return false;
                }
            }
        }
        return true;
    }
    
    // 生成完整的数独解
    public function generateSolution() {
        $this->solution = array_fill(0, $this->size, array_fill(0, $this->size, 0));
        
        // 随机填充对角线上的方格
        if ($this->size == 9) {
            for ($i = 0; $i < 9; $i += 3) {
                $this->fillBox($this->solution, $i, $i);
            }
        } else {
            for ($i = 0; $i < 4; $i += 2) {
                $this->fillBox($this->solution, $i, $i);
            }
        }
        
        $this->solveSudoku($this->solution);
    }
    
    // 填充3x3或2x2方格
    private function fillBox(&$board, $row, $col) {
        $boxSize = $this->size == 9 ? 3 : 2;
        $nums = range(1, $this->size);
        shuffle($nums);
        
        $index = 0;
        for ($i = 0; $i < $boxSize; $i++) {
            for ($j = 0; $j < $boxSize; $j++) {
                $board[$row + $i][$col + $j] = $nums[$index++];
            }
        }
    }
    
    // 根据难度移除数字生成题目
    public function generatePuzzle() {
        $this->generateSolution();
        $this->board = $this->solution;
        
        $cellsToRemove = $this->getCellsToRemove();
        $removed = 0;
        
        while ($removed < $cellsToRemove) {
            $row = rand(0, $this->size - 1);
            $col = rand(0, $this->size - 1);
            
            if ($this->board[$row][$col] != 0) {
                $backup = $this->board[$row][$col];
                $this->board[$row][$col] = 0;
                
                // 检查是否仍有唯一解
                $testBoard = $this->board;
                if ($this->solveSudoku($testBoard)) {
                    $removed++;
                } else {
                    $this->board[$row][$col] = $backup;
                }
            }
        }
    }
    
    // 根据难度获取需要移除的格子数
    private function getCellsToRemove() {
        $totalCells = $this->size * $this->size;
        
        switch ($this->difficulty) {
            case 'easy':
                return $this->size == 9 ? 40 : 8;
            case 'medium':
                return $this->size == 9 ? 50 : 10;
            case 'hard':
                return $this->size == 9 ? 60 : 12;
            case 'expert':
                return $this->size == 9 ? 65 : 14;
            default:
                return $this->size == 9 ? 50 : 10;
        }
    }
    
    public function getBoard() {
        return $this->board;
    }
    
    public function getSolution() {
        return $this->solution;
    }
    
    public function setBoard($board) {
        $this->board = $board;
    }
    
    public function checkSolution($userBoard) {
        $errors = [];
        $totalCells = 0;
        $correctCells = 0;
        
        for ($row = 0; $row < $this->size; $row++) {
            for ($col = 0; $col < $this->size; $col++) {
                if ($this->board[$row][$col] == 0) {
                    $totalCells++;
                    if ($userBoard[$row][$col] != 0) {
                        if ($userBoard[$row][$col] == $this->solution[$row][$col]) {
                            $correctCells++;
                        } else {
                            $errors[] = ['row' => $row, 'col' => $col];
                        }
                    }
                }
            }
        }
        
        return [
            'errors' => $errors,
            'totalCells' => $totalCells,
            'correctCells' => $correctCells,
            'completed' => count($errors) == 0 && $correctCells == $totalCells
        ];
    }
}

// 处理AJAX请求
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
    header('Content-Type: application/json');
    
    $action = $_POST['action'] ?? '';
    
    switch ($action) {
        case 'new_game':
            $size = 9;   //intval($_POST['size'] ?? 9);
            $difficulty = $_POST['difficulty'] ?? 'medium';
            
            $sudoku = new Sudoku($size, $difficulty);
            $sudoku->generatePuzzle();
            
            $gameId = md5(time() . rand());
            $gameData = [
                'board' => $sudoku->getBoard(),
                'solution' => $sudoku->getSolution(),
                'size' => $size,
                'difficulty' => $difficulty,
                'startTime' => time()
            ];
            
            file_put_contents("sudoku_cache/{$gameId}.json", json_encode($gameData));
            
            $_SESSION['game_id'] = $gameId;
            $_SESSION['start_time'] = time();
            
            echo json_encode([
                'success' => true,
                'gameId' => $gameId,
                'board' => $sudoku->getBoard(),
                'size' => $size,
                'difficulty' => $difficulty
            ]);
            break;
            
        case 'load_game':
            $gameId = $_POST['gameId'] ?? '';
            $cacheFile = "sudoku_cache/{$gameId}.json";
            
            if (file_exists($cacheFile)) {
                $gameData = json_decode(file_get_contents($cacheFile), true);
                $_SESSION['game_id'] = $gameId;
                $_SESSION['start_time'] = $gameData['startTime'];
                
                echo json_encode([
                    'success' => true,
                    'board' => $gameData['board'],
                    'size' => $gameData['size'],
                    'difficulty' => $gameData['difficulty']
                ]);
            } else {
                echo json_encode(['success' => false, 'message' => '游戏不存在']);
            }
            break;
            
        case 'check_solution':
            $gameId = $_SESSION['game_id'] ?? '';
            $userBoard = $_POST['board'] ?? [];
            
            if (!$gameId) {
                echo json_encode(['success' => false, 'message' => '无效的游戏会话']);
                break;
            }
            
            $cacheFile = "sudoku_cache/{$gameId}.json";
            if (file_exists($cacheFile)) {
                $gameData = json_decode(file_get_contents($cacheFile), true);
                $sudoku = new Sudoku($gameData['size'], $gameData['difficulty']);
                $sudoku->setBoard($gameData['board']);
                
                $result = $sudoku->checkSolution($userBoard);
                $result['solution'] = $gameData['solution'];
                $result['elapsedTime'] = time() - ($_SESSION['start_time'] ?? time());
                
                echo json_encode(array_merge(['success' => true], $result));
            } else {
                echo json_encode(['success' => false, 'message' => '游戏数据不存在']);
            }
            break;
            
        case 'get_solution':
            $gameId = $_SESSION['game_id'] ?? '';
            
            if (!$gameId) {
                echo json_encode(['success' => false, 'message' => '无效的游戏会话']);
                break;
            }
            
            $cacheFile = "sudoku_cache/{$gameId}.json";
            if (file_exists($cacheFile)) {
                $gameData = json_decode(file_get_contents($cacheFile), true);
                echo json_encode([
                    'success' => true,
                    'solution' => $gameData['solution'],
                    'board' => $gameData['board']
                ]);
            } else {
                echo json_encode(['success' => false, 'message' => '游戏数据不存在']);
            }
            break;
    }
    exit;
}

// 创建缓存目录
if (!file_exists('sudoku_cache')) {
    mkdir('sudoku_cache', 0777, true);
}
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>在线数独游戏 chalide.cn</title>
<meta name="author" content="yujianyue, 15058593138@qq.com">

    <style>
 *{margin:0;padding:0;box-sizing:border-box;}
 body{font-family:Arial,sans-serif;background:linear-gradient(135deg,#667eea 0%,#764ba2 100%);min-height:100vh;padding:10px;}
 .container{max-width:999px;margin:0 auto;background:white;border-radius:15px;box-shadow:0 10px 30px rgba(0,0,0,0.3);overflow:hidden;}
 .header{background:linear-gradient(45deg,#4CAF50,#45a049);color:white;padding:20px;text-align:center;}
 .header h1{font-size:28px;margin-bottom:10px;}
 .game-info{display:flex;justify-content:space-around;flex-wrap:wrap;margin-top:15px;}
 .info-item{background:rgba(255,255,255,0.2);padding:8px 15px;border-radius:20px;margin:5px;font-size:14px;}
 .controls{padding:20px;background:#f5f5f5;display:flex;justify-content:center;flex-wrap:wrap;gap:10px;}
 .control-group{display:flex;align-items:center;gap:3px;margin:2px;}
 .control-group label{font-weight:bold;color:#333;}
 select,input,button{padding:4px;border:1px solid #ddd;border-radius:5px;font-size:14px;}
 button{background:#4CAF50;color:white;border:none;cursor:pointer;transition:background 0.3s;}
 button:hover{background:#45a049;}
 .game-area{display:flex;padding:20px;gap:10px;}
 .game-board{flex:1;max-width:600px;}
 .sudoku-grid{display:grid;gap:2px;background:#333;border:1px solid #333;border-radius:5px;margin:0 auto;max-width:500px;}
 .sudoku-grid.size-9{grid-template-columns:repeat(9,1fr);grid-template-rows:repeat(9,1fr);}
 .sudoku-grid.size-4{grid-template-columns:repeat(4,1fr);grid-template-rows:repeat(4,1fr);}
 .sudoku-cell{aspect-ratio:1;background:white;border:1px solid #ddd;display:flex;align-items:center;justify-content:center;min-width:40px;min-height:40px;font-size:18px;font-weight:bold;cursor:pointer;transition:all 0.2s;}
 .sudoku-grid.size-9 .sudoku-cell:nth-child(3n):not(:nth-child(9n)),.sudoku-grid.size-9 .sudoku-cell:nth-child(6n):not(:nth-child(9n)){border-right:2px solid blue;}
 .sudoku-grid.size-9 .sudoku-cell:nth-child(n+19):nth-child(-n+27),.sudoku-grid.size-9 .sudoku-cell:nth-child(n+46):nth-child(-n+54){border-bottom:2px solid blue;}
 .sudoku-grid.size-4 .sudoku-cell:nth-child(2n){border-right:2px solid blue;}
 .sudoku-grid.size-4 .sudoku-cell:nth-child(n+5):nth-child(-n+8){border-bottom:2px solid blue;}
 .sudoku-cell:hover{background:#e3f2fd;}
 .sudoku-cell.given{background:#f0f0f0;color:#666;cursor:not-allowed;}
 .sudoku-cell.selected{background:#2196f3;color:white;}
 .sudoku-cell.error{background:#f44336;color:white;}
 .sudoku-cell.correct{background:#4caf50;color:white;}
 .virtual-keyboard{display:flex;flex-direction:column;gap:5px;min-width:220px;}
 .keyboard-title{text-align:center;font-weight:bold;color:#333;margin-bottom:10px;}
 .keyboard-grid{display:grid;grid-template-columns:repeat(5,1fr);gap:3px;}
 .keyboard-btn{width:40px;height:40px;border:2px solid #4CAF50;background:white;color:#4CAF50;font-size:18px;font-weight:bold;border-radius:5px;cursor:pointer;transition:all 0.2s;}
 .keyboard-btn:hover{background:#4CAF50;color:white;}
 .keyboard-btn.clear{background:#f44336;color:white;border-color:#f44336;}
 .keyboard-btn.clear:hover{background:#d32f2f;}
 .modal{display:none;position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.8);z-index:1000;}
 .modal-content{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);background:white;padding:30px;border-radius:10px;max-width:90%;max-height:90%;overflow-y:auto;}
 .modal-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:20px;}
 .modal-title{font-size:24px;font-weight:bold;color:#333;}
 .close-btn{background:#f44336;color:white;border:none;width:30px;height:30px;border-radius:50%;cursor:pointer;font-size:18px;}
 .result-info{margin-bottom:20px;padding:15px;background:#e8f5e8;border-radius:5px;border-left:4px solid #4CAF50;}
 .result-info.error{background:#ffebee;border-left-color:#f44336;}
 @media (max-width:768px){.game-area{flex-direction:column;align-items:center;}
 .sudoku-cell{font-size:16px;}
 .keyboard-grid{grid-template-columns:repeat(5,1fr);}
 .keyboard-btn{width:40px;height:40px;font-size:16px;}
 .controls{flex-direction:column;}
 } 
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <h1>在线数独游戏</h1>
            <div class="game-info">
                <div class="info-item">计时: <span id="timer">00:00</span></div>
                <div class="info-item">正确: <span id="correct">0</span></div>
                <div class="info-item">已填: <span id="filled">0</span></div>
                <div class="info-item">需填: <span id="total">0</span></div>
                <div class="info-item">难度: <span id="difficulty">中等</span></div>
            </div>
        </div>
        
        <div class="controls">
            <div class="control-group">
                <label for="gameId">游戏ID:</label>
                <input type="text" id="gameId" placeholder="输入游戏ID加载游戏">
                <button onclick="loadGame()">加载游戏</button>
            </div>
            
            <div class="control-group">
                <label for="gameSize">规格:</label>
                <select id="gameSize">
                    <option value="9" selected>9×9</option>
                </select>

                <label for="gameDifficulty">难度:</label>
                <select id="gameDifficulty">
                    <option value="easy">简单</option>
                    <option value="medium" selected>中等</option>
                    <option value="hard">困难</option>
                    <option value="expert">专家</option>
                </select>
            	<button onclick="newGame()">全新游戏</button>
            </div>
            <div class="control-group">
            <button onclick="checkSolution()">检查评分</button>
            <button onclick="showSolution()">显示答案</button>
            <button onclick="shareGame()">分享游戏</button>
            </div>
        </div>
        
        <div class="game-area">
            <div class="game-board">
                <div id="sudokuGrid" class="sudoku-grid size-9"></div>
            </div>
            
            <div class="virtual-keyboard">
                <div class="keyboard-title">虚拟键盘<br>先点选再输入(也可实体键盘输入)</div>
                <div class="keyboard-grid" id="keyboardGrid"></div>
            </div>
        </div>
    </div>
    
    <!-- 模态框 -->
    <div id="modal" class="modal">
        <div class="modal-content">
            <div class="modal-header">
                <div class="modal-title" id="modalTitle">标题</div>
                <button class="close-btn" onclick="closeModal()">&times;</button>
            </div>
            <div id="modalBody"></div>
        </div>
    </div>
    
    <script>
        let currentBoard = [];
        let originalBoard = [];
        let currentSize = 9;
        let selectedCell = null;
        let gameStartTime = null;
        let timerInterval = null;
        let currentGameId = '';
        
        // 初始化游戏
        function initGame() {
            newGame();
        }
        
        // 创建新游戏
        function newGame() {
            const size = parseInt(document.getElementById('gameSize').value);
            const difficulty = document.getElementById('gameDifficulty').value;
            
            fetch('', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded',
                },
                body: `action=new_game&size=${size}&difficulty=${difficulty}`
            })
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    currentBoard = data.board;
                    originalBoard = JSON.parse(JSON.stringify(data.board));
                    currentSize = data.size;
                    currentGameId = data.gameId;
                    
                    document.getElementById('gameId').value = currentGameId;
                    document.getElementById('difficulty').textContent = getDifficultyText(data.difficulty);
                    
                    renderBoard();
                    renderKeyboard();
                    startTimer();
                    updateStats();
                }
            });
        }
        
        // 加载游戏
        function loadGame() {
            const gameId = document.getElementById('gameId').value.trim();
            if (!gameId) {
                alert('请输入游戏ID');
                return;
            }
            
            fetch('', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded',
                },
                body: `action=load_game&gameId=${gameId}`
            })
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    currentBoard = data.board;
                    originalBoard = JSON.parse(JSON.stringify(data.board));
                    currentSize = data.size;
                    currentGameId = gameId;
                    
                    document.getElementById('gameSize').value = data.size;
                    document.getElementById('gameDifficulty').value = data.difficulty;
                    document.getElementById('difficulty').textContent = getDifficultyText(data.difficulty);
                    
                    renderBoard();
                    renderKeyboard();
                    startTimer();
                    updateStats();
                } else {
                    alert(data.message || '加载游戏失败');
                }
            });
        }
function renderBoard() {
  const grid = document.getElementById('sudokuGrid');
  grid.innerHTML = '';
  grid.className = `sudoku-grid size-${currentSize}`;
  
  // 计算每组的大小（3x3, 2x3, 2x2）
  const groupSize = currentSize === 9 ? 3 : currentSize === 6 ? 2 : 2;
  
  for (let i = 0; i < currentSize; i++) {
    for (let j = 0; j < currentSize; j++) {
      const cell = document.createElement('div');
      cell.className = 'sudoku-cell';
      cell.dataset.row = i;
      cell.dataset.col = j;
      
      // 添加组信息用于调试
      cell.dataset.group = `${Math.floor(i/groupSize)}-${Math.floor(j/groupSize)}`;
      
      if (originalBoard[i][j] !== 0) {
        cell.textContent = originalBoard[i][j];
        cell.classList.add('given');
      } else {
        cell.textContent = currentBoard[i][j] || '';
        cell.onclick = () => selectCell(i, j);
      }
      
      grid.appendChild(cell);
    }
  }
}        
        // 渲染数独棋盘
        function renderBoard_ooo() {
            const grid = document.getElementById('sudokuGrid');
            grid.innerHTML = '';
            grid.className = `sudoku-grid size-${currentSize}`;
            
            for (let i = 0; i < currentSize; i++) {
                for (let j = 0; j < currentSize; j++) {
                    const cell = document.createElement('div');
                    cell.className = 'sudoku-cell';
                    cell.dataset.row = i;
                    cell.dataset.col = j;
                    
                    if (originalBoard[i][j] !== 0) {
                        cell.textContent = originalBoard[i][j];
                        cell.classList.add('given');
                    } else {
                        cell.textContent = currentBoard[i][j] || '';
                        cell.onclick = () => selectCell(i, j);
                    }
                    
                    grid.appendChild(cell);
                }
            }
        }
        
        // 渲染虚拟键盘
        function renderKeyboard() {
            const keyboardGrid = document.getElementById('keyboardGrid');
            keyboardGrid.innerHTML = '';
            
            // 数字键
            for (let i = 1; i <= currentSize; i++) {
                const btn = document.createElement('button');
                btn.className = 'keyboard-btn';
                btn.textContent = i;
                btn.onclick = () => inputNumber(i);
                keyboardGrid.appendChild(btn);
            }
            
            // 清除键
            const clearBtn = document.createElement('button');
            clearBtn.className = 'keyboard-btn clear';
            clearBtn.textContent = 'X';
            clearBtn.onclick = () => inputNumber(0);
            keyboardGrid.appendChild(clearBtn);
        }
        
        // 选择单元格
        function selectCell(row, col) {
            // 清除之前的选择
            document.querySelectorAll('.sudoku-cell').forEach(cell => {
                cell.classList.remove('selected');
            });
            
            // 选择新单元格
            const cell = document.querySelector(`[data-row="${row}"][data-col="${col}"]`);
            if (cell && !cell.classList.contains('given')) {
                cell.classList.add('selected');
                selectedCell = { row, col };
            }
        }
        
        // 输入数字
        function inputNumber(num) {
            if (!selectedCell) return;
            
            const { row, col } = selectedCell;
            currentBoard[row][col] = num;
            
            const cell = document.querySelector(`[data-row="${row}"][data-col="${col}"]`);
            cell.textContent = num || '';
            
            updateStats();
        }
        
        // 检查解答
        function checkSolution() {
            fetch('', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded',
                },
                body: `action=check_solution&board=${JSON.stringify(currentBoard)}`
            })
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    showCheckResult(data);
                } else {
                    alert(data.message || '检查失败');
                }
            });
        }
        
        // 显示检查结果
        function showCheckResult(result) {
            const { errors, totalCells, correctCells, completed, solution, elapsedTime } = result;
            
            // 重置所有单元格样式
            document.querySelectorAll('.sudoku-cell').forEach(cell => {
                cell.classList.remove('error', 'correct');
            });
            
            // 标记错误单元格
            errors.forEach(({ row, col }) => {
                const cell = document.querySelector(`[data-row="${row}"][data-col="${col}"]`);
                cell.classList.add('error');
            });
            
            // 标记正确单元格
            for (let i = 0; i < currentSize; i++) {
                for (let j = 0; j < currentSize; j++) {
                    if (originalBoard[i][j] === 0 && currentBoard[i][j] !== 0) {
                        const cell = document.querySelector(`[data-row="${i}"][data-col="${j}"]`);
                        if (currentBoard[i][j] === solution[i][j]) {
                            cell.classList.add('correct');
                        }
                    }
                }
            }
            
            // 显示结果模态框
            const accuracy = totalCells > 0 ? Math.round((correctCells / totalCells) * 100) : 0;
            const timeStr = formatTime(elapsedTime);
            
            let resultHtml = `
                <div class="result-info ${completed ? '' : 'error'}">
                    <h3>${completed ? '恭喜完成！' : '还需努力！'}</h3>
                    <p>正确率: ${accuracy}% (${correctCells}/${totalCells})</p>
                    <p>用时: ${timeStr}</p>
                    <p>错误数: ${errors.length}</p>
                </div>
            `;
            
                            if (errors.length > 0) {
                resultHtml += `
                    <div class="sudoku-grid size-${currentSize}" style="margin: 20px auto;">
                `;
                
                for (let i = 0; i < currentSize; i++) {
                    for (let j = 0; j < currentSize; j++) {
                        const isOriginal = originalBoard[i][j] !== 0;
                        const isError = errors.some(e => e.row === i && e.col === j);
                        const value = isOriginal ? originalBoard[i][j] : solution[i][j];
                        
                        resultHtml += `
                            <div class="sudoku-cell ${isOriginal ? 'given' : ''} ${isError ? 'error' : ''}">
                                ${value}
                            </div>
                        `;
                    }
                }
                
                resultHtml += `</div>`;
            }
            
            showModal('检查结果', resultHtml);
        }
        
        // 显示答案
        function showSolution() {
            fetch('', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded',
                },
                body: 'action=get_solution'
            })
            .then(response => response.json())
            .then(data => {
                if (data.success) {
                    showSolutionModal(data.solution, data.board);
                } else {
                    alert(data.message || '获取答案失败');
                }
            });
        }
        
        // 显示答案模态框
        function showSolutionModal(solution, board) {
            let solutionHtml = `
                <div class="result-info">
                    <h3>完整答案</h3>
                    <p>灰色背景为题目数字，白色背景为答案</p>
                </div>
                <div class="sudoku-grid size-${currentSize}" style="margin: 20px auto;">
            `;
            
            for (let i = 0; i < currentSize; i++) {
                for (let j = 0; j < currentSize; j++) {
                    const isOriginal = board[i][j] !== 0;
                    const value = solution[i][j];
                    
                    solutionHtml += `
                        <div class="sudoku-cell ${isOriginal ? 'given' : ''}">
                            ${value}
                        </div>
                    `;
                }
            }
            
            solutionHtml += `</div>`;
            
            showModal('游戏答案', solutionHtml);
        }
        
// 分享游戏
async function shareGame() {
    if (!currentGameId) {
        alert('请先开始游戏');
        return;
    }
    
    const shareUrl = `${window.location.origin}${window.location.pathname}?id=${currentGameId}`;
    const shareText = `游戏ID: ${currentGameId}\n分享链接: ${shareUrl}`;
    
    try {
        // 优先使用 Web Share API
        if (navigator.share) {
            await navigator.share({
                title: '数独游戏分享',
                text: shareText,
                url: shareUrl
            });
            return;
        }
        
        // 尝试使用 Clipboard API
        if (navigator.clipboard) {
            await navigator.clipboard.writeText(shareText);
            alert('分享信息已复制到剪贴板');
            return;
        }
        
        // 如果都不支持，显示模态框让用户手动复制
        throw new Error('Clipboard API not available');
    } catch (err) {
        // 所有方法都失败后的降级处理
        showModal('分享游戏', `
            <div class="result-info">
                <p><strong>游戏ID:</strong> ${currentGameId}</p>
                <p><strong>分享链接:</strong> <a href="${shareUrl}" target="_blank">${shareUrl}</a></p>
                <p>请手动复制上述信息分享给朋友</p>
            </div>
        `);
        
        // 可选：自动选中文本方便用户复制
        const modal = document.querySelector('.modal-content');
        if (modal) {
            const range = document.createRange();
            range.selectNodeContents(modal);
            const selection = window.getSelection();
            selection.removeAllRanges();
            selection.addRange(range);
        }
    }
}
        
        // 显示模态框
        function showModal(title, content) {
            document.getElementById('modalTitle').textContent = title;
            document.getElementById('modalBody').innerHTML = content;
            document.getElementById('modal').style.display = 'block';
        }
        
        // 关闭模态框
        function closeModal() {
            document.getElementById('modal').style.display = 'none';
        }
        
        // 开始计时
        function startTimer() {
            if (timerInterval) {
                clearInterval(timerInterval);
            }
            
            gameStartTime = Date.now();
            timerInterval = setInterval(updateTimer, 1000);
        }
        
        // 更新计时器
        function updateTimer() {
            if (!gameStartTime) return;
            
            const elapsed = Math.floor((Date.now() - gameStartTime) / 1000);
            document.getElementById('timer').textContent = formatTime(elapsed);
        }
        
        // 格式化时间
        function formatTime(seconds) {
            const mins = Math.floor(seconds / 60);
            const secs = seconds % 60;
            return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
        }
        
        // 更新统计信息
        function updateStats() {
            let filled = 0;
            let correct = 0;
            let total = 0;
            
            for (let i = 0; i < currentSize; i++) {
                for (let j = 0; j < currentSize; j++) {
                    if (originalBoard[i][j] === 0) {
                        total++;
                        if (currentBoard[i][j] !== 0) {
                            filled++;
                        }
                    }
                }
            }
            
            // 这里简化处理，实际正确数需要通过服务器验证
            document.getElementById('filled').textContent = filled;
            document.getElementById('total').textContent = total;
            document.getElementById('correct').textContent = '?';
        }
        
        // 获取难度文本
        function getDifficultyText(difficulty) {
            const difficultyMap = {
                'easy': '简单',
                'medium': '中等',
                'hard': '困难',
                'expert': '专家'
            };
            return difficultyMap[difficulty] || '中等';
        }
        
        // 键盘事件处理
        document.addEventListener('keydown', (e) => {
            if (!selectedCell) return;
            
            const key = e.key;
            if (key >= '1' && key <= '9') {
                const num = parseInt(key);
                if (num <= currentSize) {
                    inputNumber(num);
                }
            } else if (key === 'Delete' || key === 'Backspace' || key === '0') {
                inputNumber(0);
            } else if (key === 'Escape') {
                selectedCell = null;
                document.querySelectorAll('.sudoku-cell').forEach(cell => {
                    cell.classList.remove('selected');
                });
            }
        });
        
        // 点击模态框外部关闭
        document.getElementById('modal').onclick = (e) => {
            if (e.target === document.getElementById('modal')) {
                closeModal();
            }
        };
        
        // 检查URL参数中的游戏ID
        const urlParams = new URLSearchParams(window.location.search);
        const gameIdFromUrl = urlParams.get('id');
        
        if (gameIdFromUrl) {
            document.getElementById('gameId').value = gameIdFromUrl;
            loadGame();
        } else {
            // 页面加载时初始化游戏
            document.addEventListener('DOMContentLoaded', initGame);
        }
        
        // 防止页面刷新丢失游戏状态
        window.addEventListener('beforeunload', (e) => {
            if (currentGameId && gameStartTime) {
                e.preventDefault();
                e.returnValue = '确定要离开吗？游戏进度将丢失。';
            }
        });
    </script>
</body>
</html>